
// 定义装饰器，必须接收一个参数，参数内容为类实例
function zsq(target){
    // console.log(target) // 参数target为Student类的实例
    // 为类扩展功能，添加属性和方法
    target.prototype.age = 22 
}

@zsq
class Student {
    name:string = '小王';
    shwo(){
        // console.log('show - 方法')
    }
}
let stu:any = new Student();


/**
 * 
 * 装饰器工厂
 */
function zsq2(param){
    return function iszsq(target){
        // console.log(param)  // 装饰器传递的参数
        // console.log(target)
        target.prototype.name = '我是工厂装饰器'
    }
}
@zsq2('修饰')
class Student2 {
    ahe:number = 22
}
let stu2:any = new Student2()

 /** 
  * 属性装饰器
  */
function shuXin(param){
    return function fun(vm, prototype){
        // vm：当前类原型对象
        // prototype：当前属性名
        // param：shuXin入参
        // 为属性扩展功能，为属性赋值
        vm[prototype] = param
        vm.age = 26
    }
}

class Student3 {
    @shuXin(20)
    age:number
}
let stu3:any = new Student3()
console.log(stu3.age)


 /** 
  * 方法装饰器
  */
function fangfa(param){
    // 方法装饰器可以接受三个参数
    return function (vm, method:string, descriptor){
        // vm：当前类原型对象
        // method：当前方法名
        // descriptor：descriptor表示方法描述符，value属性表示方法自身
        // param：fangfa入参
        // 为方法扩展功能：让方法可以接受并且输出传递的参数
        let oldfun = descriptor.value;
        descriptor.value = function(...args:any[]){ // 重新定义方法
            oldfun.call(this) // 调用原来的方法
            console.log(args) 
        }
    }
}

class Student4 {
    @fangfa(20)
    show(){
        console.log('方法')
    }
}
let stu4:any = new Student4()
console.log(stu4.show(1,2,3))